"""
针对依利安达的最新版算法,根据物料号获取对应的算子索引,然后根据算子的索引,获取对应使用的算子,有针对性
的进行计算.
然后板子推测宽和高的不要了,先写简化版本的,如果最后实在算不出来你,再搞高级版本的.目前就是先搞比较稳妥的算法.
数据库去添加比较好,这里最好是单独创建一个数据库,用来管理工单和算法,比如每天都创建了什么工单,然后这个工单走了什么
算法.
"""
import os
import time

import cv2

from db_tools.db_handler import DbHandler
from tools.fioman_math_tools import *
from vision_process.image_process_common import *

calcArgsDefault = {
    "1": [[2], 10, 11, 8, 15, [40, 60, 120, 150], 0.1],
    "2": [[7], 15, 11, 8, 15, [20, 30, 40], 0.5],
    "3": [[0], 11, 11, 8, 15, [30, 40, 55], 0],
    "4": [[2], 15, 15, 8, 15, [10, 20, 40], 0],
    "5": [[1], 15, 15, 8, 15, [20, 40, 60, 80], 0.1],
    "6": [[0], 15, 15, 8, 15, [5, 10, 20, 40, 55], 0]
    # "2": [[15, 120], 10, 11, 8, 15, [80, 40, 20], 0.5],
    # "4": [[4], 10, 11, 8, 20, [10,20,30,40], 0.3],
}

tryBeginIndex = 1
calcArgs1 = {
    "1": [[2], 13, 11, 8, 15, [10, 30, 40, 50, 60], 0.2],
    "2": [[2], 17, 11, 8, 15, [10, 20, 40, 50, 60], 0],
}

db = DbHandler()
cp = ConfigParams()
calcArgsUsed = None
jointLineExtend = 23
upDownSlice = int(50 * cp.mm2pix)


def find_middle_line(board, boardPos, edgeLineAngle, splitNumber):
    # 首先是这里中缝找不到了,将这个board分成5等分,然后每个等分求一个矩形,然后将求得的矩形和之前的斜率做对比
    # 求出斜率差值最小的那个就是要求的斜率.
    offset = board.shape[1] // splitNumber
    findLineKb = []
    for i in range(splitNumber):
        boardUsed = board[:, offset * i:offset * (i + 1)]
        image_show("BoardUsed_{}".format(i + 1), boardUsed)
        cnts = cv2.findContours(boardUsed.copy(), cv.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv2.contourArea, reverse=True)
        if len(cnts) == 0:
            continue
        _, (w, h), _ = cv2.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv2.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        if boardPos == "up":
            middleError = board.shape[0] - get_two_points_middle(leftBottom, rightBottom)[1]
        else:
            middleError = get_two_points_middle(leftTop, rightTop)[1]
        print("MiddleError: {}".format(middleError))
        if middleError < 10 * cp.mm2pix:
            continue
        useImage = cv2.cvtColor(boardUsed, cv2.COLOR_GRAY2BGR)
        cv2.drawContours(useImage, [rectBoxPoints], -1, colorGreen, 2)
        image_show("MiddleLineFinded_{}".format(i + 1), useImage)
        if boardPos == "up":
            findLineKb.append(get_line_k_and_b(leftBottom, rightBottom))
        else:
            findLineKb.append(get_line_k_and_b(leftTop, rightTop))

    if len(findLineKb) > 0:
        cv2.destroyAllWindows()
        # 按照K和B进行排序,选出和传入的角度出差最小的
        lineKRes = sorted(findLineKb, key=lambda x: abs(edgeLineAngle - get_angle_by_k(x[0])))
        return lineKRes[0]
    else:
        return None


def check_inner_board_2p(board, width, height, calcThresBig, calcThresSmall, boardColor, boardPos, upBox,
                         heightHalf, isSizeCheck, totalBoard):
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidth13 = int(totalWidthPix * 0.15)
    moveWidthMid = int(totalWidthPix * 0.15)
    moveHeight = int(totalHeightPix * 0.25)
    boardArea = width * height
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }
    widthMax = width / cp.mm2pix + calcThresBig
    widthMin = width / cp.mm2pix - calcThresSmall
    heightMax = height / cp.mm2pix + calcThresBig
    heightMin = height / cp.mm2pix - calcThresSmall
    widthMm = width / cp.mm2pix
    heightMm = height / cp.mm2pix
    moveAngleUsed = board.copy()

    try:
        if boardPos == "up":
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0),
                         (moveAngleUsed.shape[1] - moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight),
                         (moveWidthMid, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed,
                         (moveAngleUsed.shape[1] - moveWidthMid, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)
        else:
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0),
                         (moveAngleUsed.shape[1] - moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight),
                         (moveWidth13, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed,
                         (moveAngleUsed.shape[1] - moveWidth13, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)

        image_show("MoveAngle", moveAngleUsed)

        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cnts) == 0:
            res["result"] = "error"
            res["info"] = "{}框 找内板失败,没有找到任何的轮廓".format(boardPos)
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - widthMm, 2), round(totalHeightMm - heightMm, 2))
            return res
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        # 判断是不是没有中缝,如果底边接近底部10个mm,并且是上框,或者是下框,上边接近顶部10个mm以内
        # 推测是没有中缝的情况,如果不是尺寸确认那里
        if boardPos == "up":
            edgeLineAngle = get_angle_by_k(get_line_k(leftTop, rightTop))
            yOffset = (get_two_points_middle(leftBottom, rightBottom)[1] - board.shape[0]) // cp.mm2pix
            print("上框信息: 第一边角度: {:.3f},中缝底部偏移: {}".format(edgeLineAngle, yOffset))
        else:
            edgeLineAngle = get_angle_by_k(get_line_k(leftBottom, rightBottom))
            yOffset = (get_two_points_middle(leftTop, rightTop)[1]) // cp.mm2pix
            print("下框信息: 第三边角度:{:.3f},中缝底部偏移:{}".format(edgeLineAngle, yOffset))

        middleIsOk = True
        # 重新计算一次leftTop,RightTop,rightBotto,leftBottom
        if abs(yOffset) < 10:
            middleIsOk = False
            middleLineKB = find_middle_line(board, boardPos, edgeLineAngle, 4)
            if middleLineKB is None:
                middleLineKB = find_middle_line(board, boardPos, edgeLineAngle, 6)
            if middleLineKB is None:
                middleLineKB = find_middle_line(board, boardPos, edgeLineAngle, splitNumber=8)
            if middleLineKB is not None:
                middleIsOk = True
                middleK, middleB = middleLineKB
                leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
                rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
                if boardPos == "up":
                    leftBottom = get_two_lines_intersection(leftK, leftB, middleK, middleB)
                    leftBottom = int(leftBottom[0]), int(leftBottom[1])
                    rightBottom = get_two_lines_intersection(rightK, rightB, middleK, middleB)
                    rightBottom = int(rightBottom[0]), int(rightBottom[1])
                else:
                    leftTop = get_two_lines_intersection(leftK, leftB, middleK, middleB)
                    leftTop = int(leftTop[0]), int(leftTop[1])
                    rightTop = get_two_lines_intersection(rightK, rightB, middleK, middleB)
                    rightTop = int(rightTop[0]), int(rightTop[1])

        if not middleIsOk:
            res["result"] = "error"
            res["info"] = "{}框 找内板失败,找到的中缝位置不对".format(boardPos)
            return res

        useImage = boardColor.copy()
        cv.drawContours(useImage, [np.array([leftTop, rightTop, rightBottom, leftBottom])], -1,
                        (0, 255, 0), 3)
        image_show("InnerBoardFinded", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(get_two_point_distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(get_two_point_distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = (round(widthFinded - widthMm, 2), round(heightFinded - heightMm, 2))
        areaFinded = w * h
        if areaFinded < 0.7 * boardArea:
            res["result"] = "error"
            res["info"] = "{}框 找内板失败,找到的内板面积过小".format(boardPos)
            return res
        elif areaFinded > 1.3 * boardArea:
            res["result"] = "error"
            res["info"] = "{}框 找内板失败,找到的内板面积过大".format(boardPos)
            return res
        else:
            if isSizeCheck:
                if widthFinded < widthMin or heightFinded < heightMin:
                    res["result"] = "small"
                    res["info"] = "{} 框,识别尺寸过小,识别尺寸: {}".format(boardPos, res["calcSize"])
                    return res
                if widthFinded > widthMax or heightFinded > heightMax:
                    res["result"] = "big"
                    res["info"] = "{} 框,识别尺寸过大,识别尺寸: {}".format(boardPos, res["calcSize"])
                    return res
            else:
                if heightFinded < heightMin:
                    res["result"] = "small"
                    res["info"] = "高度识别过小,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                    return res
                if heightFinded > heightMax:
                    res["result"] = "big"
                    res["info"] = "高度识别过大,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                    return res
                if widthFinded < widthMin:
                    res["result"] = "small"
                    res["info"] = "宽度识别过小,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                    return res
                if widthFinded > widthMax:
                    res["result"] = "big"
                    res["info"] = "宽度识别过大,识别尺寸:{},识别误差:{}".format(res["calcSize"], res["calcError"])
                    return res
            boxFinded = res["box"]
            if boardPos == "down":
                downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in boxFinded]
                # 检测是否叠板
                isOverlap = check_two_box_is_overlap(upBox, downBoxPoints)
                if isOverlap:
                    totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
                    cv.drawContours(totalBoardColor, [np.array(upBox), np.array(downBoxPoints)],
                                    -1, colorGreen, 3)
                    image_show("BoardOverLap", totalBoardColor)
                    res["result"] = "error"
                    res["info"] = "上下框出现叠板,识别失败~"
                    return res

            res["result"] = "ok"
            res["info"] = "识别成功!"
            return res
    except Exception as e:
        errorInfo = "in check_inner_board_2p(),error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidthMm, totalHeightMm)
        res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2),
                            round(totalHeightMm - height / cp.mm2pix, 2))
        return res


def get_inner_board_info_2p(board, jointLine1, width, height, calcThresBig, calcThresSmall,
                            boardPos, isFirstCheck=False, upBox=None, heightHalf=None,
                            isSizeCheck=False, totalBoard=None):
    """
    双拼板获取内板信息,最近的思路是根据亮度去获取算子.
    :param board: 要识别的内板
    :param jointLine1:
    :param jointLine2:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param boardPos:
    :param isFirstCheck:
    :param upBox:
    :param heightHalf:
    :param isSizeCheck:
    :param totalBoard:
    :return:
    """
    boardColor = cv.cvtColor(board.copy(), cv2.COLOR_GRAY2BGR)
    sizeOkByExtendRes = []
    sizeDifRes = []
    sizeOkRes = []
    # 找到板子的中心
    boardHeight, boardWidth = board.shape[:2]
    boardCenter = (boardWidth // 2, (boardHeight - upDownSlice) // 2)
    cv2.circle(boardColor, boardCenter, 5, colorGreen, -1)
    image_show("BoardCenter", boardColor)
    centerUsed = board.copy()[boardCenter[1] - height // 3:boardCenter[1] + height // 3,
                 boardCenter[0] - width // 3:boardCenter[0] + width // 3]
    image_show("CenterUsed", centerUsed)
    centerMeanVal = int(np.mean(centerUsed))
    totalMeanVal = int(np.mean(board))
    print("centerMeanVal:{},totalMeanVal:{},difVal:{}".format(centerMeanVal, totalMeanVal,
                                                              totalMeanVal - centerMeanVal))
    calcArgsUsed = calcArgs1
    for tryTimes in range(tryBeginIndex, len(calcArgsUsed.keys()) + 1):
        cv2.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = (
            calcArgsUsed.get(str(tryTimes)))
        print(f"第{tryTimes}次计算,计算参数:(高斯半径:{gaussianR},方差核:{squareR},"
              f"腐蚀膨胀核:{dilateKernel}, 膨胀腐蚀次数:{dilateTimes},腐蚀膨胀次数:{erodeTimes},"
              f"识别阈值offset:{thresOffsetList},scharr比例:{scharrRate})")
        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.convertScaleAbs(scharrXY)
            scharrXY = cv.bitwise_and(scharrXY, jointLine1)
        image_show("ScharrXY", scharrXY)
        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)
        image_show("squareDifDilateErore", contourImg)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv2.destroyAllWindows()
            image_show("thresBefore", squareDifErode)
            # 根据阈值进行分割
            centerX, centerY = int(squareDifErode.shape[1] / 2), int(squareDifErode.shape[0] / 2)
            yChoosePos = int(0.25 * squareDifErode.shape[0])
            xChoosePos = int(0.25 * squareDifErode.shape[1])
            thresUsed = squareDifErode[centerY - yChoosePos:centerY + yChoosePos,
                        centerX - xChoosePos:centerX + xChoosePos]
            chooseRoiThres = int(np.mean(thresUsed))
            thresUsedReal = chooseRoiThres + thresOffset
            print("第 {} 个阈值,使用的实际阈值:{},参考的中心区域亮度值:{},thresOffset:{}".format(index + 1,
                                                                                                 thresUsedReal, chooseRoiThres, thresOffset))
            _, contourImg = cv.threshold(squareDifErode, thresUsedReal, 255, cv.THRESH_BINARY)
            image_show("boardThres_({})".format(thresUsedReal), contourImg)
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, cv.bitwise_not(jointLine1))
            image_show("SubtractImage", contourImg)

            #     # 4. 进行泛洪填充,要考虑一种情况是,填充选择的点刚好不是黑点,是个白点的情况.要重新再选一次
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            if contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2] > 150:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 3, contourImg.shape[0] // 3), 150)
            else:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 2, contourImg.shape[0] // 2), 150)

            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            # floodFill = cv.bitwise_not(contourImg)
            image_show("FloodFill", floodFill)

            # 进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)
            res = check_inner_board_2p(floodFill, width, height, calcThresBig, calcThresSmall, boardColor,
                                       boardPos, upBox, heightHalf, isSizeCheck, totalBoard)
            print("计算结果:{},{},识别尺寸:{},{},误差:{}".format(res["result"], res["info"], res["calcSize"],
                                                                 (int(res["calcSize"][0] * cp.mm2pix),
                                                                  int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            if res["result"] == "ok":
                sizeOkRes.append(res)
                calcSize = res["calcSize"]
                calcError = res["calcError"]
                if get_sum_abs(calcError) < 7 and not isFirstCheck:
                    print("返回的ok结果是:算子编号和亮度阈值:({},{}),尺寸:{},{},误差:{}"
                          .format(tryTimes, thresOffset, calcSize, (int(calcSize[0] * cp.mm2pix),
                                                                    int(calcSize[1] * cp.mm2pix)), calcError))
                    return "ok", res["info"], res["box"]
                continue
            elif res["result"] != "error":
                sizeDifRes.append(res)
                if (res["result"]) == "big":
                    break
                if res["result"] == "small":
                    continue
                continue

    else:
        if isFirstCheck and isSizeCheck:
            sizeList = []
            boxList = []
            if len(sizeOkRes) >= 1:
                resOkSorted = sorted(sizeOkRes, key=lambda x: get_sum_abs(x["calcError"]))
                for res in resOkSorted:
                    sizeList.append(res["calcSize"])
                    boxList.append(res["box"])
                return "ok", sizeList, boxList

            if len(sizeDifRes) >= 1:
                resSizeDifList = sorted(sizeDifRes, key=lambda x: get_sum_abs(x["calcError"]))
                for res in resSizeDifList:
                    sizeList.append(res["calcSize"])
                    boxList.append(res["box"])
                return "sizeDif", sizeList, boxList

            else:
                return "error", "内板寻找失败", None
        else:
            if len(sizeOkRes) >= 1:
                resOkSorted = sorted(sizeOkRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resOkSorted[0]
                print("返回的ok结果是:尺寸:{},{},误差:{}"
                      .format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
                return "ok", res["info"], res["box"]

            if len(sizeOkByExtendRes) >= 1:
                resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resOkSorted[0]
                print("返回的ok结果是:尺寸:{},{},误差:{}"
                      .format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
                return "ok", res["info"], res["box"]

            if len(sizeDifRes) >= 1:
                resDifSorted = sorted(sizeDifRes, key=lambda x: get_sum_abs(x["calcError"]))
                res = resDifSorted[0]
                return "sizeDif", res["info"], res["box"]
            else:
                return "error", "找内板失败", None


def get_size_check_result_2pin(image, width, height, calcThresBig, totalBoardBox,
                               totalBoardNoAngle, layoutMode="竖排"):
    if image is None:
        return "error", "图像异常,请重拍", None, None, None
    jointLineMask = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 0
    jointLineMask[:, cp.middleJointPos2 - jointLineExtend:cp.middleJointPos2 + jointLineExtend] = 0
    jointLineMaskNoAnglel, _ = get_board_without_angle(jointLineMask, totalBoardBox)

    cv2.destroyAllWindows()
    image_show("TotalBoard", totalBoardNoAngle)

    w, h = totalBoardBox[1]
    heightHalf = int(h / 2)
    upBoard = totalBoardNoAngle.copy()[:int(heightHalf + upDownSlice), :]
    upJointLine1 = jointLineMaskNoAnglel.copy()[:int(heightHalf + upDownSlice), :]
    upBoardColor = cv.cvtColor(upBoard, cv2.COLOR_GRAY2BGR)

    upRes, upSizes, upBoxes = get_inner_board_info_2p(upBoard, upJointLine1, width, height,
                                                      calcThresBig, calcThresBig, "up", isFirstCheck=True, upBox=None,
                                                      heightHalf=heightHalf, isSizeCheck=True, totalBoard=totalBoardNoAngle)
    upBoardResList = []
    upSizeResList = []
    if upRes != "error":
        for index, upBox in enumerate(upBoxes):
            if upBox is not None:
                upBoardRes = upBoardColor.copy()
                cv.drawContours(upBoardRes, [np.array(upBox)], -1, colorGreen, 3)
                centerX, centerY = upBoard.shape[1] // 2, upBoard.shape[0] // 2
                cv.putText(upBoardRes, "{}".format(index + 1), (centerX - 8, centerY),
                           cv.FONT_HERSHEY_COMPLEX, 10, colorBlue, 5)
                image_show("upBoardRes", upBoardRes)
                upBoardResList.append(upBoardRes)
                upSizeResList.append(upSizes[index])
        return "ok", upSizeResList, upBoardResList, upBoardColor
    else:
        return "error", "内板识别出错", None, upBoardColor


def get_boxes_2pin(image, width, height, calcThresBig, calcThresSmall, totalBoardBox,
                   totalBoard, isFirstBoard, layoutMode="竖排"):
    """
    两拼板,获取内板信息
    :param image:
    :param width:
    :param height:
    :param calcThresBig:
    :param calcThresSmall:
    :param totalBoardBox:
    :param totalBoard:
    :param isFirstBoard:
    :return:
    """
    jointLineMask1 = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask1[:, cp.middleJointPos - jointLineExtend:cp.middleJointPos + jointLineExtend] = 0
    jointLineMask1[:, cp.middleJointPos2 - jointLineExtend:cp.middleJointPos2 + jointLineExtend] = 0
    jointLineMaskNoAngle1, _ = get_board_without_angle(jointLineMask1, totalBoardBox)
    cv.destroyAllWindows()
    image_show("TotalBoard", totalBoard)

    w, h = totalBoardBox[1]
    heightHalf = int(h / 2)
    upBoard = totalBoard.copy()[:int(heightHalf + upDownSlice), :]
    upJointLine1 = jointLineMaskNoAngle1.copy()[:int(heightHalf + upDownSlice), :]
    downBoard = totalBoard.copy()[int(heightHalf - upDownSlice):, :]
    downJointLine1 = jointLineMaskNoAngle1.copy()[int(heightHalf - upDownSlice):, :]

    upRes, upInfo, upBox = get_inner_board_info_2p(
        upBoard, upJointLine1, width, height, calcThresBig, calcThresSmall,
        "up", isFirstCheck=isFirstBoard, isSizeCheck=False, totalBoard=totalBoard)
    if upRes != "ok":
        return False, upInfo, upBox, None

    downRes, downInfo, downBox = get_inner_board_info_2p(
        downBoard, downJointLine1, width, height, calcThresBig, calcThresSmall,
        "down", isFirstCheck=isFirstBoard, upBox=upBox, heightHalf=heightHalf,
        isSizeCheck=False, totalBoard=totalBoard)
    if downRes != "ok":
        return False, downInfo, upBox, downBox
    downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in downBox]
    totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
    cv.drawContours(totalBoardColor, [np.array(upBox), np.array(downBoxPoints)],
                    -1, colorGreen, 3)
    image_show("TwoBoxes", totalBoardColor)
    downBox = downBoxPoints
    return True, "识别成功", upBox, downBox


def get_lines_with_boxes(image, totalBoardNoAnlge, totalBoardBox, totalBoardThresWithAngle,
                         upBox, downBox, transMtx, topRemain, leftRemain, bottomRemain,
                         rightRemain, totalBoardOffset):
    if len(image.shape) == 3:
        image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)

    _, (w, h), totalBoardAngle = totalBoardBox
    # print ((cx, cy), (w, h), totalBoardAngle)
    upLeftTop, upRightTop, upRightBottom, upLeftBottom = upBox
    downLeftTop, downRightTop, downRightBottom, downLeftBottom = downBox

    middleOffsetPix = int(cp.mm2pix * cp.middleOffset)
    # 识别框补偿,上框上移1个mm,下框上移一个mm.
    upLeftTop = [upLeftTop[0], upLeftTop[1] - middleOffsetPix]
    upRightTop = [upRightTop[0], upRightTop[1] - middleOffsetPix]
    upRightBottom = [upRightBottom[0], upRightBottom[1] - middleOffsetPix]
    upLeftBottom = [upLeftBottom[0], upLeftBottom[1] - middleOffsetPix]

    downLeftTop = [downLeftTop[0], downLeftTop[1] - middleOffsetPix]
    downRightTop = [downRightTop[0], downRightTop[1] - middleOffsetPix]
    downRightBottom = [downRightBottom[0], downRightBottom[1] - middleOffsetPix]
    downLeftBottom = [downLeftBottom[0], downLeftBottom[1] - middleOffsetPix]

    # cut_remain_pix_acbd如果不等于-1，则证明需要切割ac，bd边，那就需要进行下面的计算

    leftCutLineK = get_linear_fit_k_vertical(np.array([upLeftTop, upLeftBottom,
                                                       downLeftTop, downLeftBottom]))
    # 直接分别求过四个点的直线的b参数，找出最值
    if leftCutLineK is None:
        leftCutLineB = min(upLeftTop[0], upLeftBottom[0], downLeftTop[0],
                           downLeftBottom[0]) - leftRemain
    else:
        upLeftTopX = upLeftTop[1] - (upLeftTop[0] - leftRemain) * leftCutLineK
        upLeftBottomX = upLeftBottom[1] - (upLeftBottom[0] - leftRemain) * leftCutLineK
        downLeftTopX = downLeftTop[1] - (downLeftTop[0] - leftRemain) * leftCutLineK
        downLeftBottomX = downLeftBottom[1] - (downLeftBottom[0] - leftRemain) * leftCutLineK

        if leftCutLineK > 0:  # 当k大于0时，b越大，越靠左
            leftCutLineB = max(upLeftTopX, upLeftBottomX, downLeftTopX, downLeftBottomX)
        else:  # 当k小于0时，b越小，越靠左
            leftCutLineB = min(upLeftTopX, upLeftBottomX, downLeftTopX, downLeftBottomX)

    rightCutLineK = get_linear_fit_k_vertical(np.array([upRightBottom, upRightTop,
                                                        downRightTop, downRightBottom]))
    # 直接分别求过四个点的直线的b参数，找出最值
    if rightCutLineK is None:
        rightCutLineB = max(upRightTop[0], upRightBottom[0], downRightTop[0],
                            downRightBottom[0]) + rightRemain
    else:
        upRightTopX = upRightTop[1] - (upRightTop[0] + rightRemain) * rightCutLineK
        upRightBottomX = upRightBottom[1] - (upRightBottom[0] + rightRemain) * rightCutLineK
        downRightTopX = downRightTop[1] - (downRightTop[0] + rightRemain) * rightCutLineK
        downRightBottomX = downRightBottom[1] - (downRightBottom[0] + rightRemain) * rightCutLineK

        if rightCutLineK > 0:  # 当k大于0时，b越大，越靠左
            rightCutLineB = min(upRightTopX, upRightBottomX, downRightTopX, downRightBottomX)
        else:  # 当k小于0时，b越小，越靠左
            rightCutLineB = max(upRightTopX, upRightBottomX, downRightTopX, downRightBottomX)

    topCutLineK = get_line_k(upLeftTop, upRightTop)
    if topCutLineK is None:
        cv.destroyAllWindows()
        return False, None, None
    else:
        topCutLineB = topCutLineK * -1 * (upLeftTop[0]) + (upLeftTop[1] - topRemain)

    bottomCutLineK = get_line_k(downLeftBottom, downRightBottom)
    if bottomCutLineK is None:
        # 垂直，一定是异常的
        cv.destroyAllWindows()
        return False, None, None, None
    else:
        bottomCutLineB = (bottomCutLineK * -1 * (downLeftBottom[0])
                          + downLeftBottom[1] + bottomRemain)

    # 四边都不切的逻辑寻找边线的算法
    boardLeftTop = [0, 0]
    boardRightTop = [w, 0]
    boardLeftBottom = [0, h]
    boardRightBottom = [w, h]

    # # 先将切线超过1,3边范围的的留边宽度置为0，也就是如果边线算出去了,就沿着物料区域的最外侧1个mm去切
    # leftTopY = upLeftTop[1] - topRemain
    # rightTopY = upRightTop[1] - topRemain
    # if leftTopY < 0 or rightTopY < 0:
    #     topRemain = 0

    # leftBottomY = downLeftBottom[1] + bottomRemain
    # rightBottomY = downRightBottom[1] + bottomRemain
    # if leftBottomY > totalBoard.shape[0] or rightBottomY > totalBoard.shape[0]:
    #     bottomRemain = 0

    findEdgeExtend = int(7 * cp.mm2pix)  # 找边缘的时候延长10个mm
    totalBoardExtendForFindEdge, _ = get_board_without_angle_3(image, totalBoardBox, findEdgeExtend)
    totalBoardThresForFindEdge, _ = get_board_without_angle_3(totalBoardThresWithAngle, totalBoardBox, findEdgeExtend)

    if topRemain == 0:
        topLineK, topLineB = find_first_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge, findEdgeExtend, upLeftTop, upRightTop)
        if topLineK is not None:
            topCutLineK, topCutLineB = topLineK, topLineB
        else:
            topCutLineK, topCutLineB = get_line_k_and_b(boardLeftTop, boardRightTop)
    if bottomRemain == 0:
        bottomLineK, bottomLineB = find_third_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge, findEdgeExtend)
        if bottomLineK is not None:
            bottomCutLineK, bottomCutLineB = bottomLineK, bottomLineB
        else:
            bottomCutLineK, bottomCutLineB = get_line_k_and_b(boardLeftBottom, boardRightBottom)
    if leftRemain == 0:
        leftCutLineK, leftCutLineB = get_line_k_and_b(boardLeftBottom, boardLeftTop)
    if rightRemain == 0:
        rightCutLineK, rightCutLineB = get_line_k_and_b(boardRightTop, boardRightBottom)

    # ①求所有的交点，当上下左右四条边都切时

    leftTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, leftCutLineK, leftCutLineB)
    rightTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, rightCutLineK, rightCutLineB)
    leftBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, leftCutLineK, leftCutLineB)
    rightBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, rightCutLineK, rightCutLineB)

    if leftTopCross[0] is None or rightTopCross[0] is None or leftBottomCross[0] is None or \
            rightBottomCross[0] is None:
        cv.destroyAllWindows()
        return False, None, None, None
    extend = int(8 * cp.mm2pix)
    extendLeftRight = int(23 * cp.mm2pix)

    topCutLeftPoint = [- extend, topCutLineK * (- extend) + topCutLineB]
    topCutRightPoint = [extend + w, topCutLineK * (extend + w) + topCutLineB]

    # bottomCutRightPoint = [w + 10,
    #                        bottomCutLineK * (w + 10) + bottomCutLineB]

    bottomCutRightPoint = [w + extend, bottomCutLineK * (w + extend) + bottomCutLineB]
    bottomCutLeftPoint = [- extend, bottomCutLineK * (- extend) + bottomCutLineB]

    if leftCutLineK is None:
        leftCutLineBottom = [leftCutLineB, leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [leftCutLineB, leftTopCross[1] - extendLeftRight]
    elif leftCutLineK != 0:
        leftCutLineBottom = [((leftBottomCross[1] + extendLeftRight) - leftCutLineB) / leftCutLineK,
                             leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [(leftTopCross[1] - extendLeftRight - leftCutLineB) / leftCutLineK,
                          leftTopCross[1] - extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    if rightCutLineK is None:
        rightCutLineTop = [rightCutLineB, rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [rightCutLineB, rightBottomCross[1] + extendLeftRight]
    elif rightCutLineK != 0:
        rightCutLineTop = [((rightTopCross[1] - extendLeftRight) - rightCutLineB) / rightCutLineK,
                           rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [((rightBottomCross[1] + extendLeftRight) - rightCutLineB) / rightCutLineK,
                              rightBottomCross[1] + extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    # 求中线，如果求出来k和top，bottom差太多就返回错误
    middleCutLine = get_middle_cut_line(upLeftBottom, upRightBottom, downLeftTop, downRightTop)

    if middleCutLine[0] is None:
        # 垂直，一定是异常
        cv.destroyAllWindows()
        return False, None, None, None
    leftMiddleCross = get_two_lines_intersection(middleCutLine[0], middleCutLine[1], leftCutLineK, leftCutLineB)
    rightMiddleCross = get_two_lines_intersection(middleCutLine[0], middleCutLine[1], rightCutLineK, rightCutLineB)

    middleCutLineLeft = [leftMiddleCross[0] - 10,
                         (leftMiddleCross[0] - 10) * middleCutLine[0] + middleCutLine[1]]
    middleCutLineRight = [rightMiddleCross[0] + 10,
                          (rightMiddleCross[0] + 10) * middleCutLine[0] + middleCutLine[1]]

    # 变成大图中的点
    # cx, cy表示板的中心点，w，h是板的宽高，rotateAngle表示要旋转的角度
    (centerX, centerY), (w, h), totalBoardAngle = totalBoardBox
    rotatedCenter = (centerX, centerY)

    wHalf, hHalf = w // 2 - 1, h // 2 - 1
    M = cv.getRotationMatrix2D(rotatedCenter, -totalBoardAngle, 1)
    centerOffset = totalBoardOffset

    # 获取物料区域在大图上的四个点的坐标.
    boardLeftTopBig = np.dot(M, [boardLeftTop[0] + centerOffset[0], boardLeftTop[1] + centerOffset[1], 1])
    boardRightTopBig = np.dot(M, [boardRightTop[0] + centerOffset[0], boardRightTop[1] + centerOffset[1], 1])
    boardRightBottomBig = np.dot(M, [boardRightBottom[0] + centerOffset[0], boardRightBottom[1] + centerOffset[1], 1])
    boardLeftBottomBig = np.dot(M, [boardLeftBottom[0] + centerOffset[0], boardLeftBottom[1] + centerOffset[1], 1])

    topCutLeftPointBig = np.dot(M, [topCutLeftPoint[0] + centerOffset[0], topCutLeftPoint[1] + centerOffset[1], 1])
    topCutRightPointBig = np.dot(M, [topCutRightPoint[0] + centerOffset[0], topCutRightPoint[1] + centerOffset[1], 1])
    bottomCutRightPointBig = np.dot(M, [bottomCutRightPoint[0] + centerOffset[0], bottomCutRightPoint[1] + centerOffset[1], 1])
    bottomCutLeftPointBig = np.dot(M, [bottomCutLeftPoint[0] + centerOffset[0], bottomCutLeftPoint[1] + centerOffset[1], 1])
    leftCutLineBottomBig = np.dot(M, [leftCutLineBottom[0] + centerOffset[0], leftCutLineBottom[1] + centerOffset[1], 1])
    leftCutLineTopBig = np.dot(M, [leftCutLineTop[0] + centerOffset[0], leftCutLineTop[1] + centerOffset[1], 1])
    rightCutLineTopBig = np.dot(M, [rightCutLineTop[0] + centerOffset[0], rightCutLineTop[1] + centerOffset[1], 1])
    rightCutLineBottomBig = np.dot(M, [rightCutLineBottom[0] + centerOffset[0], rightCutLineBottom[1] + centerOffset[1], 1])
    middleCutLineLeftBig = np.dot(M, [middleCutLineLeft[0] + centerOffset[0], middleCutLineLeft[1] + centerOffset[1], 1])
    middleCutLineRightBig = np.dot(M, [middleCutLineRight[0] + centerOffset[0], middleCutLineRight[1] + centerOffset[1], 1])

    # 重新将端点定位到大图上去
    upLeftBottom = np.dot(M, [upLeftBottom[0] + centerOffset[0], upLeftBottom[1] + centerOffset[1], 1])
    upRightBottom = np.dot(M, [upRightBottom[0] + centerOffset[0], upRightBottom[1] + centerOffset[1], 1])
    upLeftTop = np.dot(M, [upLeftTop[0] + centerOffset[0], upLeftTop[1] + centerOffset[1], 1])
    upRightTop = np.dot(M, [upRightTop[0] + centerOffset[0], upRightTop[1] + centerOffset[1], 1])
    downLeftTop = np.dot(M, [downLeftTop[0] + centerOffset[0], downLeftTop[1] + centerOffset[1], 1])
    downLeftBottom = np.dot(M, [downLeftBottom[0] + centerOffset[0], downLeftBottom[1] + centerOffset[1], 1])
    downRightTop = np.dot(M, [downRightTop[0] + centerOffset[0], downRightTop[1] + centerOffset[1], 1])
    downRightBottom = np.dot(M, [downRightBottom[0] + centerOffset[0], downRightBottom[1] + centerOffset[1], 1])

    # 画出内框
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upRightBottom[0]), int(upRightBottom[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upLeftTop[0]), int(upLeftTop[1])), (0, 0, 255),
            3)
    cv.line(imageColor, (int(upRightBottom[0]), int(upRightBottom[1])), (int(upRightTop[0]), int(upRightTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(upLeftTop[0]), int(upLeftTop[1])), (int(upRightTop[0]), int(upRightTop[1])), (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])),
            (int(downRightBottom[0]), int(downRightBottom[1])), (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])), (int(downLeftTop[0]), int(downLeftTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(downRightBottom[0]), int(downRightBottom[1])), (int(downRightTop[0]), int(downRightTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftTop[0]), int(downLeftTop[1])), (int(downRightTop[0]), int(downRightTop[1])),
            (0, 0, 255), 3)

    # 画出上，下，左，右，中五条切线

    cv.line(imageColor, (int(topCutLeftPointBig[0]), int(topCutLeftPointBig[1])),
            (int(topCutRightPointBig[0]), int(topCutRightPointBig[1])), (0, 255, 0), 3)
    cv.putText(imageColor, '1', (int((topCutLeftPointBig[0] + topCutRightPointBig[0]) / 2),
                                 int((topCutLeftPointBig[1] + topCutRightPointBig[1]) / 2) - 60), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0),
               12)
    cv.line(imageColor, (int(bottomCutRightPointBig[0]), int(bottomCutRightPointBig[1])),
            (int(bottomCutLeftPointBig[0]), int(bottomCutLeftPointBig[1])), (0, 255, 0), 3)
    cv.putText(imageColor, '3', (int((bottomCutRightPointBig[0] + bottomCutLeftPointBig[0]) / 2),
                                 int((bottomCutRightPointBig[1] + bottomCutLeftPointBig[1]) / 2) + 140),
               cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)

    cv.line(imageColor, (int(leftCutLineBottomBig[0]), int(leftCutLineBottomBig[1])),
            (int(leftCutLineTopBig[0]), int(leftCutLineTopBig[1])), (255, 0, 0), 3)
    cv.putText(imageColor, '2', (int((leftCutLineBottomBig[0] + leftCutLineTopBig[0]) / 2) + 80,
                                 int((leftCutLineBottomBig[1] + leftCutLineTopBig[1]) / 2)), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)
    cv.line(imageColor, (int(rightCutLineTopBig[0]), int(rightCutLineTopBig[1])),
            (int(rightCutLineBottomBig[0]), int(rightCutLineBottomBig[1])), (255, 0, 0), 3)
    cv.putText(imageColor, '4',
               (int((rightCutLineTopBig[0] + rightCutLineBottomBig[0]) / 2) - 80,
                int((rightCutLineTopBig[1] + rightCutLineBottomBig[1]) / 2)), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)
    cv.line(imageColor, (int(middleCutLineLeftBig[0]), int(middleCutLineLeftBig[1])),
            (int(middleCutLineRightBig[0]), int(middleCutLineRightBig[1])), (0, 255, 0), 3)

    # 综合10个点的信息
    topCutLeftPointRobot = pix_pos_to_robot(topCutLeftPointBig, transMtx)
    topCutRightPointRobot = pix_pos_to_robot(topCutRightPointBig, transMtx)
    bottomCutLeftPointRobot = pix_pos_to_robot(bottomCutLeftPointBig, transMtx)
    bottomCutRightPointRobot = pix_pos_to_robot(bottomCutRightPointBig, transMtx)
    leftCutLineBottomRobot = pix_pos_to_robot(leftCutLineBottomBig, transMtx)
    leftCutLineTopRobot = pix_pos_to_robot(leftCutLineTopBig, transMtx)
    rightCutLineTopRobot = pix_pos_to_robot(rightCutLineTopBig, transMtx)
    rightCutLineBottomRobot = pix_pos_to_robot(rightCutLineBottomBig, transMtx)
    middleCutLineLeftRobot = pix_pos_to_robot(middleCutLineLeftBig, transMtx)
    middleCutLineRightRobot = pix_pos_to_robot(middleCutLineRightBig, transMtx)

    boardLeftTopRobot = pix_pos_to_robot(boardLeftTopBig, transMtx)
    boardRightTopRobot = pix_pos_to_robot(boardRightTopBig, transMtx)
    boardRightBottomRobot = pix_pos_to_robot(boardRightBottomBig, transMtx)
    boardLeftBottomRobot = pix_pos_to_robot(boardLeftBottomBig, transMtx)
    # 计算裁切面积和刀使用的长度
    cutDisTotal = 0
    cutAreaTotal = 0
    if topRemain != 0:
        cutDis = distance(topCutLeftPointRobot, topCutRightPointRobot)
        area = cutDis * (distance(get_two_points_middle(topCutLeftPointRobot, topCutRightPointRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardRightTopRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis
    if leftRemain != 0:
        cutDis = distance(leftCutLineBottomRobot, leftCutLineTopRobot)
        area = cutDis * (distance(get_two_points_middle(leftCutLineBottomRobot, leftCutLineTopRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardLeftBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if bottomRemain != 0:
        cutDis = distance(bottomCutRightPointRobot, bottomCutLeftPointRobot)
        area = cutDis * (distance(get_two_points_middle(bottomCutRightPointRobot, bottomCutLeftPointRobot),
                                  get_two_points_middle(boardLeftBottomRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if rightRemain != 0:
        cutDis = distance(rightCutLineTopRobot, rightCutLineBottomRobot)
        area = cutDis * (distance(get_two_points_middle(rightCutLineTopRobot, rightCutLineBottomRobot),
                                  get_two_points_middle(boardRightTopRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    imageResut, _ = get_board_without_angle(imageColor, totalBoardBox, extend=80)
    image_show("resultImage", imageResut)
    # 以裁切机的实际切线为标准，计算前板长，后板长，总长
    # 先算中线中点
    firstBoardLength, totalBoardLength = get_board_length(
        [topCutLeftPointRobot, topCutRightPointRobot],
        [middleCutLineLeftRobot, middleCutLineRightRobot],
        [bottomCutLeftPointRobot, bottomCutRightPointRobot])
    # 计算top_middle 和bottom_middle的角度,全部调整成一个方向,需要逆时针调整的时候为负数.
    topMiddleAngle = get_two_line_angle(middleCutLineRightRobot, middleCutLineLeftRobot,
                                        topCutRightPointRobot, topCutLeftPointRobot)  # 获取第一个角度
    bottomMiddleAngle = get_two_line_angle(middleCutLineRightRobot, middleCutLineLeftRobot,
                                           bottomCutRightPointRobot, bottomCutLeftPointRobot)  # 获取第二个角度
    # 是否切第一刀:
    isFirstCut = True if topRemain != 0 else False
    isThirdCut = True if bottomRemain != 0 else False
    cutLength = [round(cutDisTotal, 5), round(cutAreaTotal, 5)]
    cutWidth = distance(topCutLeftPointRobot, topCutRightPointRobot)
    return [topCutLeftPointRobot, topCutRightPointRobot, bottomCutRightPointRobot,
            bottomCutLeftPointRobot, leftCutLineBottomRobot, leftCutLineTopRobot,
            rightCutLineTopRobot, rightCutLineBottomRobot, middleCutLineLeftRobot,
            middleCutLineRightRobot, firstBoardLength, totalBoardLength, topMiddleAngle,
            bottomMiddleAngle], imageResut, cutLength, isFirstCut, isThirdCut, cutWidth


if __name__ == '__main__':
    # 先加载参数
    filePath = r"D:\2024\sanqiang"
    layoutMode = "竖排"
    isFirstBoard = True  # 是否是首片,首片有首片的算法逻辑
    res, data = db.get_line_cam_check_thres()
    totalHeightMax = data.get("totalHeightMax")
    totalHeightMin = data.get("totalHeightMin")
    boardBreak = False
    calcThresBigGlobal = 20
    calcThresSmallGlobal = 9
    innerToEdgeThres = 5
    jointNumber = "2"
    mtx = [
        [0, 1, 0],
        [1, 0, 0]
    ]
    remainEdge = [0, 15, 0, 15]
    topRemain, leftRemain, bottomRemain, rightRemain = [int(x * cp.mm2pix) for x in remainEdge]
    keepDir = filePath
    if not os.path.isdir(keepDir):
        keepDir, _ = os.path.split(filePath)

    keepOkPath = os.path.join(keepDir, "ok")
    keepOkResPath = os.path.join(keepDir, "cutlines")
    keepFailPath = os.path.join(keepDir, "fail")
    if not os.path.exists(keepOkPath):
        os.mkdir(keepOkPath)
    if not os.path.exists(keepOkResPath):
        os.mkdir(keepOkResPath)
    if not os.path.exists(keepFailPath):
        os.mkdir(keepFailPath)

    fileNames = []  # 保存要去识别的所有的图片
    if os.path.isfile(filePath):
        filePath, fileName = os.path.split(filePath)
        fileNames.append(fileName)
    else:
        for root, dirs, files in os.walk(filePath):
            if root != filePath:
                continue
            for file in files:
                if file[-4:] != ".bmp":
                    continue
                fileNames.append(file)

    for index, fileName in enumerate(fileNames):
        filePathReal = os.path.join(filePath, fileName)
        srcW, srcH, upLineOffset, downLineOffset = get_width_height_by_image_name_2p(fileName)
        if srcW is None or srcH is None:
            print("*" * 10 + "第 {} 张图 ({}),图像名称错误,已经跳过".format(index + 1, fileName) + "*" * 10)
            continue
        if 0 in upLineOffset or 0 in downLineOffset:
            isFirstBoard = True
        else:
            isFirstBoard = True
        print("*" * 10 + " 第 {} 张图 ({})".format(index + 1, fileName) + "*" * 10)
        imageTest = cv.imread(filePathReal, cv.IMREAD_GRAYSCALE)
        calcStart = time.time()
        totalBoardRes = check_total_board_is_ok(imageTest, totalHeightMax, totalHeightMin,
                                                boardBreak, jointNumber, layoutMode)
        (res, hintInfo, totalBoardBox, totalBoardNoAngle, totalBoardOffset,
         totalBoardThresWithAngle, totalBoardResWithAngle) = totalBoardRes
        print("物料检测结果: {}, {}".format(res, hintInfo))
        if isFirstBoard:
            #
            resFirst, boardSizeList, boardResList, upBoard = get_size_check_result_2pin(
                imageTest, srcW, srcH, calcThresBigGlobal, totalBoardBox, totalBoardNoAngle)
            res, info, upBox, downBox = get_boxes_2pin(
                imageTest, srcW, srcH, calcThresBigGlobal, calcThresSmallGlobal, totalBoardBox,
                totalBoardNoAngle, isFirstBoard)
        else:
            res, info, upBox, downBox = get_boxes_2pin(
                imageTest, srcW, srcH, calcThresBigGlobal, calcThresSmallGlobal,
                totalBoardBox, totalBoardNoAngle, isFirstBoard)

        if res:
            cutLines, imageRes, cutDis, isFirstCut, isThirdCut, cutWidth = get_lines_with_boxes(
                imageTest, totalBoardNoAngle, totalBoardBox, totalBoardThresWithAngle, upBox,
                downBox, mtx, topRemain, leftRemain, bottomRemain, rightRemain, totalBoardOffset)
            print("算法耗时: {}".format(time.time() - calcStart))
            os.remove(filePathReal)
            imageRes = get_size_scale_image(imageRes, sizeScale=3)
            cv.imwrite(os.path.join(keepOkResPath, fileName), imageRes)
            cv.imwrite(os.path.join(keepOkPath, fileName), imageTest)
            print("识别成功")
            continue
        else:
            print("算法耗时: {}".format(time.time() - calcStart))
            cv.imwrite(os.path.join(keepFailPath, fileName), imageTest)
            os.remove(filePathReal)
            print("识别失败XXXXXXXXXXXXXXXXX")
            continue
